package com.dss.auto_deploy.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dss.auto_deploy.config.DssProperties;
import com.dss.auto_deploy.config.WebsocketEndPoint;
import com.dss.auto_deploy.constants.AutoConstants;
import com.dss.auto_deploy.domain.*;
import com.dss.auto_deploy.dto.GitlabPushDto;
import com.dss.auto_deploy.dto.WsSendDto;
import com.dss.auto_deploy.enums.BooleanTypeEnum;
import com.dss.auto_deploy.mapper.*;
import com.dss.auto_deploy.service.*;
import com.dss.auto_deploy.util.*;
import com.dss.auto_deploy.util.mail.MailUtil;
import com.dss.auto_deploy.util.mail.MyEmail;
import com.github.dockerjava.api.DockerClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description:
 * @author: dongshoushan
 */
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor = @_(@Autowired))
public class GitlabPushServiceImpl implements IGitlabPushService {
    private final AdmDockerDeployMapper admDockerDeployMapper;
    private final AdmProjectMapper admProjectMapper;
    private final IAdmDockerDeployService admDockerDeployService;
    private final IDeployMapper deployMapper;
    private final IDeployService deployService;
    private final AdmProjectAutoConfigMapper admProjectAutoConfigMapper;
    private final MailUtil mailUtil;
    private final DssProperties dssProperties;
    private final AdmNamespaceMapper admNamespaceMapper;
    private final AdmDockerRegistryMapper admDockerRegistryMapper;
    private final IServerService serverService;
    private final IAdmDockerService admDockerService;
    private final DockerUtil dockerUtil;
    private final WebsocketEndPoint websocketEndPoint;
    private final AdmUserMapper admUserMapper;
    private final String baseLocalPath = System.getProperty("user.dir") + "/temp/config/npm";
    private final String mavenLocalPath = System.getProperty("user.dir") + "/temp/config/maven";

    /**
     * @param dto dto
     * @description: 部署
     * @author: dongshoushan
     * @date:2022-11-23 20:56:40
     */
    @Override
    public synchronized void toDeployDocker(GitlabPushDto dto) {
        GitlabPushDto.Project project = dto.getProject();
        String branch = "";
        String tag = "";
        //push操作
        if ("push".equals(dto.getObject_kind())) {
            branch = dto.getRef().replace("refs/heads/", "");
        } else if ("tag_push".equals(dto.getObject_kind())) {
            //打master的tag
            branch = "master";
            tag = dto.getRef().replace("refs/tags/", "");
        } else {
            System.out.println("只处理push和tag");
            return;
        }
        String projectName = project.getName();
        String url = project.getUrl();
        url = url.replace("10.121.136.150", "10.121.138.210");
        AdmProject admProject = admProjectMapper.getToDeploay(projectName);
        if (admProject == null) {
            log.error("未配置此项目：{}", projectName);
            return;
        }
        Long projectId = admProject.getId();
        //拉代码 分支/项目名称
        String localPath = StringUtils.format("{}{}/{}/{}", dssProperties.getSystemPrefix(), AutoConstants.GIT_WORKSPACE, branch, projectName);
        try {
            gitCloneOrPull(localPath, branch, admProject, projectName);
            AdmProjectAutoConfig autoConfig = admProjectAutoConfigMapper.selectOne(Wrappers.lambdaQuery(AdmProjectAutoConfig.class)
                    .eq(AdmProjectAutoConfig::getProjectId, projectId).eq(AdmProjectAutoConfig::getBranch, branch));
            if (autoConfig == null){
                return;
            }
            if ("push".equals(dto.getObject_kind())) {
                //要部署的docker节点id、docker部署
                changeState(dto, branch, projectName, url);
                List<Long> idList = admDockerDeployMapper.selectToDeployDocker(branch, projectName, url);
                if (CollectionUtil.isNotEmpty(idList) && autoConfig.getState() == 1) {
                    //自动只更新所提交的模块内容
                    deployJavaAuto(dto, branch, projectName, admProject, idList);
                    return;
                }
                //只构建test分支到测试仓库不部署节点不进行pull，不需要配置节点。源码地址取dev分支的相关路径进行替换===一般是test分支
                List<Long> devIdList = admDockerDeployMapper.selectToDeployDocker("dev", projectName, url);
                if (CollectionUtil.isNotEmpty(devIdList) && autoConfig.getState() == 2) {
                    deployToRegistry(dto, admProject, branch, projectId, projectName, autoConfig);
                    return;
                }
                //前端部署
                deploayHtml(dto, branch, projectName, url, admProject);
            } else if ("tag_push".equals(dto.getObject_kind())) {
                //部署打tag的构建
                deployTag(dto, admProject, projectId, branch, projectName, tag, url,autoConfig);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void deployJavaAuto(GitlabPushDto dto, String branch, String projectName,  AdmProject admProject, List<Long> idList) throws Exception {
        sendWebsocket(dto, admProject, branch);
        log.info("=============开始部署后端：{},节点id：{}============", projectName, JacksonUtils.toString(idList));
        admDockerDeployService.init();
        //生成maven编译脚本
        List<AdmDockerDeploy> list = admDockerDeployService.listByIds(idList);
        String maven = generateCompilationScript(branch, projectName, list,admProject);
        //编译
        //if (true) {
        if (admDockerDeployService.mavenBuild(maven, list)) {
            List<Long> namespaceIds = list.stream().map(AdmDockerDeploy::getNamespaceId).distinct().sorted(Comparator.comparing(Long::intValue)).collect(Collectors.toList());
            for (Long namespaceId : namespaceIds) {
                //去重，要上传和编译的配置数据
                QueryWrapper<AdmDockerDeploy> wrapper = Wrappers.query();
                wrapper.lambda().in(AdmDockerDeploy::getId, idList).eq(AdmDockerDeploy::getNamespaceId, namespaceId).groupBy(AdmDockerDeploy::getModuleName);
                List<AdmDockerDeploy> uploadList = admDockerDeployService.list(wrapper);
                for (AdmDockerDeploy dockerDeploy : uploadList) {
                    try {
                        admDockerDeployService.uploadService(dockerDeploy);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("=============全部构建完毕，开始push==========");
                for (AdmDockerDeploy dockerDeploy : uploadList) {
                    try {
                        AdmNamespace admNamespace = admNamespaceMapper.selectById(namespaceId);
                        AdmDockerRegistry admDockerRegistry = admDockerRegistryMapper.selectById(admNamespace.getRegistryId());
                        //仓库虚拟机
                        Server registryServer = serverService.getServerById(admDockerRegistry.getServerId());
                        //仓库所在docker
                        AdmDocker registryDocker = admDockerService.getByIp(registryServer.getIp());
                        DockerClient registryDockerClient = dockerUtil.getDockerClientByDocker(SpringUtils.getBean(AdmDockerServiceImpl.class).convertToVo(registryDocker));
                        String imageName = StringUtils.format("{}:{}/{}:{}", registryServer.getIp(), admDockerRegistry.getPort(), dockerDeploy.getModuleName(), dockerDeploy.getTag());
                        admDockerDeployService.pushImageCmd(registryDockerClient, imageName, dockerDeploy);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                websocketEndPoint.send(WsSendDto.builder().type(1).table("index").data(StringUtils.format("当前构建状态空闲,上次部署时间：{}", DateUtils.getTime())).build());
            }
        } else {
            sendBuildFailMsg(dto);
        }
    }

    private void deployToRegistry(GitlabPushDto dto, AdmProject admProject, String branch, Long projectId, String projectName, AdmProjectAutoConfig autoConfig) throws Exception {
        sendWebsocket(dto, admProject, branch);
        AdmProjectAutoConfig devConfig = admProjectAutoConfigMapper.getByDevConfig(projectId);
        //后端构建
        List<AdmDockerDeploy> admDockerDeployList = admDockerDeployMapper.selectToBulid(devConfig.getNamespaceId(), devConfig.getProjectId());
        if (CollectionUtil.isNotEmpty(admDockerDeployList)) {
            String tag = admDockerDeployList.get(0).getTag();
            String maven = generateCompilationScript(branch, projectName, admDockerDeployList,admProject);
            System.out.println(StringUtils.format("===========开始构建后端{}镜像{}==========", branch, admProject.getProjectName()));
            String userName = dto.getUser_name();
            MyEmail email = MyEmail.builder().subject(StringUtils.format("【构建{}镜像】{}", branch, admProject.getProjectName()))
                    .receiver(StringUtils.isNotEmpty(userName)?StringUtils.format("{}@lenovo.com",userName,dto.getUser_email()):admProject.getTeamMembersMail()).build();
            //maven编译master待上线
            try {
                if (admDockerDeployService.buildMaster(maven)) {
                    //推送
                    admDockerDeployService.imageToRegistry(tag, branch, admProject, admDockerDeployList,autoConfig);
                    pushMsgToUser(admProject, branch, autoConfig, admDockerDeployList, email, tag);
                } else {
                    email.setText("maven编译后端待上线镜像失败:" + projectName);
                }
            } catch (Exception e) {
                log.error(e.getMessage());
                email.setText("构建后端待上线镜像失败:" + e.getMessage());
            } finally {
                try {
                    mailUtil.sendMail(email);
                } catch (Exception e) {
                    throw new ServiceException(e.getMessage());
                }
            }
        }
    }

    private void pushMsgToUser(AdmProject admProject, String branch, AdmProjectAutoConfig autoConfig, List<AdmDockerDeploy> admDockerDeployList, MyEmail email, String tag) {
        Long namespaceId = autoConfig.getNamespaceId();
        AdmNamespace admNamespace = admNamespaceMapper.selectById(namespaceId);
        Long registryId = admNamespace.getRegistryId();
        AdmDocker admDocker = admDockerService.getByRegistryId(registryId);
        Server server = serverService.getServerByDockerId(admDocker.getId());
        String names = admDockerDeployList.stream().map(AdmDockerDeploy::getModuleName).collect(Collectors.joining(","));
        String dateStr = DateUtils.parseDateToStr(DateUtils.YYYYMMDD, new Date());
        email.setText(StringUtils.format("后端镜像【{}】构建完成，本次tag版本:{},更新模块：{}.<br/><br/>  " +
                        "1.本次更新的镜像包已打好压缩包,请直接下载或者执行scp进行远程拷贝,目录位于{}虚拟机/data/{}。<br/>" +
                        "例如执行 scp /data/{}/* root@192.168.29.32:/home/setup/release/ecgw/{} 密码输入:dvx_A8k4 <br/><br/>" +
                        "2.把镜像压缩包上传到测试或者线上环境，先删除旧的容器和镜像，再执行load命令，例如docker load -i /data/temp/lenovo-ne.tar <br/><br/>" +
                        "3.在测试或线上执行 /usr/local/bin/docker-compose -f /data/temp/docker-compose/docker-compose.yml up -d 命令重新启动容器",
                branch, tag, names, server.getIp(), admProject.getProjectName(), admProject.getProjectName(), dateStr));
        websocketEndPoint.send(WsSendDto.builder().type(1).table("index").data(StringUtils.format("当前构建状态空闲,上次部署时间：{}", DateUtils.getTime())).build());
    }

    private void gitCloneOrPull(String localPath, String branch, AdmProject admProject, String projectName) throws IOException {
        File localPathFile = new File(localPath);
        FileUtils.createFilePath(StringUtils.format("{}{}/{}", dssProperties.getSystemPrefix(), AutoConstants.GIT_WORKSPACE, branch));
        if (!localPathFile.exists()) {
            String cmd = StringUtils.format("cmd /k cd /d  {}{}/{} && git clone -b {} {}",
                    dssProperties.getSystemPrefix(), AutoConstants.GIT_WORKSPACE, branch, branch, admProject.getGitUrl());
            System.out.println(cmd);
            Runtime.getRuntime().exec(cmd);
            log.info("=============执行git clone成功============");
        } else {
            String cmd = StringUtils.format("cmd /k cd /d  {}{}/{}/{} && git pull",
                    dssProperties.getSystemPrefix(), AutoConstants.GIT_WORKSPACE, branch, projectName);
            System.out.println(cmd);
            Runtime.getRuntime().exec(cmd);
            log.info("=============执行git pull成功=============");
        }
        log.info(String.format("代码已拉取到本地%s", localPath));
    }

    private void deploayHtml(GitlabPushDto dto, String branch, String projectName, String url, AdmProject admProject) throws Exception {
        List<Deploy> deployList = deployMapper.selectToDeploy(branch, projectName, url);
        List<Long> htmlIdList = deployList.stream().filter(deploy -> deploy.getType() == 1).map(Deploy::getId).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(htmlIdList)) {
            sendWebsocket(dto, admProject, branch);
            for (Deploy deploy : deployList) {
                FileUtils.deleteFile(deploy.getLocalFile());
            }
            //构建前端
            buildHtml(branch, projectName, dto);
            //自动部署前端
            deployService.javaScriptDeployBatch(htmlIdList);
            websocketEndPoint.send(WsSendDto.builder().type(1).table("index").data(StringUtils.format("当前构建状态空闲,上次部署时间：{}", DateUtils.getTime())).build());
        }
    }

    private void deployTag(GitlabPushDto dto, AdmProject admProject, Long projectId, String branch, String projectName, String tag, String url,AdmProjectAutoConfig autoConfig) throws Exception {
        System.out.println("项目开始构建待上线的：" + JacksonUtils.toString(admProject));
        //查询不是master的
        AdmProjectAutoConfig devConfig = admProjectAutoConfigMapper.getByDevConfig(projectId);
        if (devConfig != null && autoConfig != null) {
            sendWebsocket(dto, admProject, branch);
            //后端构建
            List<AdmDockerDeploy> admDockerDeployList = admDockerDeployMapper.selectToBulid(devConfig.getNamespaceId(), devConfig.getProjectId());
            if (CollectionUtil.isNotEmpty(admDockerDeployList)) {
                String maven = generateCompilationScript(branch, projectName, admDockerDeployList,admProject);
                System.out.println(StringUtils.format("===========开始构建后端待上线镜像{}==========", admProject.getProjectName()));
                MyEmail email = MyEmail.builder().subject(StringUtils.format("【构建待上线镜像】{}", admProject.getProjectName())).receiver(admProject.getTeamMembersMail()).build();
                //maven编译master待上线
                try {
                    if (admDockerDeployService.buildMaster(maven)) {
                        //推送
                        admDockerDeployService.imageToRegistry(tag, branch, admProject, admDockerDeployList,autoConfig);
                        Long namespaceId = autoConfig.getNamespaceId();
                        AdmNamespace admNamespace = admNamespaceMapper.selectById(namespaceId);
                        Long registryId = admNamespace.getRegistryId();
                        if (BooleanTypeEnum.YES.getCode().equals(admProject.getTagToProd())) {
                            List<String> moduleNameList = admDockerDeployList.stream().map(AdmDockerDeploy::getModuleName).distinct().collect(Collectors.toList());
                            //上传镜像到生产
                            admDockerDeployService.uploadImagesToProd(tag, projectId, registryId, moduleNameList);
                        }
                        String names = admDockerDeployList.stream().map(AdmDockerDeploy::getModuleName).collect(Collectors.joining(","));
                        if (BooleanTypeEnum.YES.getCode().equals(admProject.getTagToProd())) {
                            email.setText(StringUtils.format("后端生产环境自动部署完毕。本次更新模块：{}", names));
                        } else {
                            AdmDocker admDocker = admDockerService.getByRegistryId(registryId);
                            Server server = serverService.getServerByDockerId(admDocker.getId());
                            String dateStr = DateUtils.parseDateToStr(DateUtils.YYYYMMDD, new Date());
                            email.setText(StringUtils.format("后端镜像【{}】构建完成，本次tag版本:{},更新模块：{}.<br/><br/>  " +
                                            "1.本次更新的镜像包已打好压缩包,请直接下载或者执行scp进行远程拷贝,目录位于{}虚拟机/data/{}。<br/>" +
                                            "例如执行 scp /data/{}/* root@192.168.29.32:/home/setup/release/ecgw/{} 密码输入:dvx_A8k4 <br/><br/>" +
                                            "2.把镜像压缩包上传到测试或者线上环境，先删除旧的容器和镜像，再执行load命令，例如docker load -i /data/temp/lenovo-ne.tar <br/><br/>" +
                                            "3.在测试或线上执行 /usr/local/bin/docker-compose -f /data/temp/docker-compose/docker-compose.yml up -d 命令重新启动容器",
                                    branch, tag, names, server.getIp(), admProject.getProjectName(), admProject.getProjectName(), dateStr));
                        }
                        websocketEndPoint.send(WsSendDto.builder().type(1).table("index").data(StringUtils.format("当前构建状态空闲,上次部署时间：{}", DateUtils.getTime())).build());
                    } else {
                        email.setText("maven编译后端待上线镜像失败:" + projectName);
                    }
                } catch (Exception e) {
                    log.error(e.getMessage());
                    email.setText("构建后端待上线镜像失败:" + e.getMessage());
                } finally {
                    try {
                        mailUtil.sendMail(email);
                    } catch (Exception e) {
                        throw new ServiceException(e.getMessage());
                    }
                }
            } else {
                //前端构建
                System.out.println(StringUtils.format("===========开始构建前端待上线代码{}==========", admProject.getProjectName()));
                List<Deploy> deployList = deployMapper.selectToDeploy(branch, projectName, url);
                for (Deploy deploy : deployList) {
                    FileUtils.deleteFile(deploy.getLocalFile());
                }
                buildHtml(branch, projectName, dto);
                MyEmail email = MyEmail.builder().subject(StringUtils.format("【构建前端待上线代码】{}", admProject.getProjectName())).receiver(admProject.getTeamMembersMail()).build();
                email.setText(StringUtils.format("构建前端待上线镜像成功，请前往<a href='http://192.168.29.180:8088/page/index.html' style=\"color:#1890ff\">" +
                        "自动部署网站</a>=>普通部署菜单，手动执行部署"));
                try {
                    mailUtil.sendMail(email);
                    websocketEndPoint.send(WsSendDto.builder().type(1).table("index").data(StringUtils.format("当前构建状态空闲,上次部署时间：{}", DateUtils.getTime())).build());
                } catch (Exception e) {
                    throw new ServiceException(e.getMessage());
                }
            }
        }
    }

    private void sendWebsocket(GitlabPushDto dto, AdmProject admProject, String branch) {
        String userName = dto.getUser_name();
        List<AdmProjectAutoConfig> autoConfigList = admProjectAutoConfigMapper.selectList(Wrappers.lambdaQuery(AdmProjectAutoConfig.class)
                .eq(AdmProjectAutoConfig::getProjectId, admProject.getId())
                .eq(AdmProjectAutoConfig::getBranch, branch)
                .ne(AdmProjectAutoConfig::getState, 0));
        Long namespaceId = autoConfigList.get(0).getNamespaceId();
        AdmNamespace admNamespace = admNamespaceMapper.selectById(namespaceId);
        String data = StringUtils.format("当前构建项目：{}【{}】,命名空间：{}.", admProject.getProjectName(), branch, admNamespace.getName());
        if (userName == null) {
            data += StringUtils.format("页面手动触发");
        } else {
            AdmUser admUser = admUserMapper.selectOne(Wrappers.lambdaQuery(AdmUser.class).eq(AdmUser::getMail, userName + "@lenovo.com"));
            List<GitlabPushDto.CommitsItem> commits = dto.getCommits();
            String message;
            if (commits.size() == 1) {
                message = commits.get(0).getMessage();
            } else {
                message = commits.stream().map(GitlabPushDto.CommitsItem::getMessage).filter(s -> !s.contains("Merge branch")).findFirst().orElse("");
            }
            data += StringUtils.format("提交人：{}，提交内容为：{}", admUser.getRealName(), message);
        }
        websocketEndPoint.send(WsSendDto.builder().type(0).table("index").data(StringUtils.format(data)).build());
    }

    private void changeState(GitlabPushDto dto, String branch, String projectName, String url) {
        List<GitlabPushDto.CommitsItem> list = dto.getCommits();
        if (list == null || list.isEmpty()) {
            return;
        }
        List<String> commitsList = new ArrayList<>();
        list.forEach(commitsItem -> {
            commitsList.addAll(commitsItem.getAdded());
            commitsList.addAll(commitsItem.getModified());
            commitsList.addAll(commitsItem.getRemoved());
        });
        if (commitsList.isEmpty()) {
            return;
        }
        List<AdmDockerDeploy> deployList = admDockerDeployMapper.selectAllDeployDocker(branch, projectName, url);
        List<String> moduleNameList = deployList.stream().map(AdmDockerDeploy::getModuleName).distinct().collect(Collectors.toList());
        Boolean update = false;
        for (String moduleName : moduleNameList) {
            Boolean flag = false;
            for (String commits : commitsList) {
                if (commits.contains(moduleName)) {
                    flag = true;
                    update = true;
                }
            }
            List<AdmDockerDeploy> admDockerDeploys = deployList.stream().filter(s -> s.getModuleName().equals(moduleName)).collect(Collectors.toList());
            //有本次的提交记录则更新为启用
            if (flag) {
                admDockerDeploys.forEach(deployDeploy -> deployDeploy.setEnable(0));
            } else {
                admDockerDeploys.forEach(deployDeploy -> deployDeploy.setEnable(1));
            }
        }
        //能匹配到模块记录的才去更新，否则不更新，项目不一定按照模块更新
        if (update) {
            admDockerDeployService.updateBatchById(deployList);
        }
    }

    private void sendBuildFailMsg(GitlabPushDto dto) {
        String userName = dto.getUser_name();
        if (StringUtils.isNotEmpty(userName)) {
            MyEmail email = MyEmail.builder().subject(StringUtils.format("【构建失败】{}", dto.getProject().getName())).receiver(userName + "@lenovo.com").build();
            email.setText(StringUtils.format("maven构建失败：项目：{}，分支：{} 此代码提交人：{}",
                    dto.getProject().getName(), dto.getRef().replace("refs/heads/", ""), userName));
            try {
                mailUtil.sendMail(email);
                System.out.println(JacksonUtils.toString(email));
            } catch (Exception e) {
                throw new ServiceException(e.getMessage());
            }
        }
    }

    /**
     * 生成maven编译脚本
     *
     * @param branch
     * @param projectName
     * @return
     * @throws Exception
     */
    private String generateCompilationScript(String branch, String projectName, List<AdmDockerDeploy> list,  AdmProject admProject) throws Exception {
        String jdkVersion = list.get(0).getJdkVersion();
        String profilesActive = list.get(0).getSpringProfilesActive();
        String buildPath = StringUtils.format("{}/{}/{}/maven.bat", mavenLocalPath, branch, projectName);
        Map<String, Object> map = new HashMap<>(2);
        map.put("path", StringUtils.format("{}{}/{}/{}{}",
                dssProperties.getSystemPrefix(), AutoConstants.GIT_WORKSPACE, branch, projectName, StringUtils.isNotEmpty(admProject.getFolder()) ? admProject.getFolder() : ""));
        map.put("command", "mvn clean install -T 1C -Dmaven.test.skip=true -Dmaven.compile.fork=true  -P" + profilesActive);
        if ("jdk8".equals(jdkVersion)) {
            map.put("javaHome", StringUtils.format("set JAVA_HOME={}{}", dssProperties.getSystemPrefix(), dssProperties.getJdkDto().getJdk8Path()));
        } else if ("jdk17".equals(jdkVersion)) {
            map.put("javaHome", StringUtils.format("set JAVA_HOME={}{}", dssProperties.getSystemPrefix(), dssProperties.getJdkDto().getJdk17Path()));
        } else if ("jdk19".equals(jdkVersion)) {
            map.put("javaHome", StringUtils.format("set JAVA_HOME={}{}", dssProperties.getSystemPrefix(), dssProperties.getJdkDto().getJdk19Path()));
        }

        FileUtils.generateFileByTemplate("mavenBuild.ftl", buildPath, mavenLocalPath + "/" + branch + "/" + projectName, map);
        return StringUtils.format("cmd /c {}", buildPath);
    }

    /**
     * 构建前端
     *
     * @param branch
     * @param projectName
     * @throws Exception
     */
    private void buildHtml(String branch, String projectName, GitlabPushDto dto) throws Exception {
        log.info("=============开始build前端：{}============", projectName);
        String installPath = baseLocalPath + "/" + branch + "/" + projectName + "/npmInstall.bat";
        Map<String, Object> installMap = new HashMap<>();
        installMap.put("path", StringUtils.format("{}{}/{}/{}", dssProperties.getSystemPrefix(), AutoConstants.GIT_WORKSPACE, branch, projectName));
        installMap.put("command", "npm install --legacy-peer-deps");
        System.out.println("执行 npm install --legacy-peer-deps");
        FileUtils.generateFileByTemplate("build.ftl", installPath, baseLocalPath + "/" + branch + "/" + projectName, installMap);
        String install = StringUtils.format("cmd /c {}", installPath);

        System.out.println(install);
        Thread.sleep(2000);
        Process p = Runtime.getRuntime().exec(install);
        InputStream is = p.getInputStream();
        String s;
        LineNumberReader lnr = new LineNumberReader(new InputStreamReader(is, "gbk"));
        while ((s = lnr.readLine()) != null) {
            //System.out.println(s);
            if (s.contains("for details")) {
                break;
            }
        }
        is.close();
        log.info("=============执行npm install成功============");
        String buildPath = baseLocalPath + "/" + branch + "/" + projectName + "/npmBuild.bat";
        Map<String, Object> buildMap = new HashMap<>();
        String path = StringUtils.format("{}{}/{}/{}", dssProperties.getSystemPrefix(), AutoConstants.GIT_WORKSPACE, branch, projectName);
        buildMap.put("path", path);
        buildMap.put("command", "npm run build:prod");
        System.out.println("执行 npm run build:prod");
        FileUtils.generateFileByTemplate("build.ftl", buildPath, baseLocalPath + "/" + branch + "/" + projectName, buildMap);
        String build = StringUtils.format("cmd /c {}", buildPath);
        System.out.println(build);
        Process p2 = Runtime.getRuntime().exec(build);
        InputStream is2 = p2.getInputStream();
        String s2;
        LineNumberReader lnr2 = new LineNumberReader(new InputStreamReader(is2, "gbk"));
        long start = System.currentTimeMillis();
        while ((s2 = lnr2.readLine()) != null) {
            //System.out.println(s2);
            if (s2.contains("Build complete")) {
                break;
            }
            if (System.currentTimeMillis() - start > 10 * 60 * 1000) {
                String userName = dto.getUser_name();
                if (StringUtils.isNotEmpty(userName)) {
                    MyEmail email = MyEmail.builder().subject(StringUtils.format("【构建失败】{}", dto.getProject().getName())).receiver(userName + "@lenovo.com").build();
                    email.setText(StringUtils.format("前端构建已超过10分钟：项目：{}，分支：{} 此代码提交人：{}。请前往跳板机目录：{}处理确认是否代码冲突，是否能正常打zip包",
                            dto.getProject().getName(), dto.getRef().replace("refs/heads/", ""), userName, path));
                    try {
                        mailUtil.sendMail(email);
                        System.out.println(JacksonUtils.toString(email));
                    } catch (Exception e) {
                        throw new ServiceException(e.getMessage());
                    }
                }
            }
            if (System.currentTimeMillis() - start > 10 * 60 * 1000) {
                throw new ServiceException("当前构建已超过10分钟，请确认是否代码冲突重新拉取处理");
            }
            //Thread.sleep(5000);
        }
        is2.close();
        log.info("=============执行npm build成功============");
    }


}
